using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace PKGames
{
	public class GridLayoutDataSource
	{
		protected GameObject _cellPrefab;

		private IGridCellData[] _gridCellData;

		private RectTransform _cellAnchor;

		private GridLayoutGroup _cellGrid;

		private RectTransform _content;

		private RectTransform _viewPort;

		private GridLayoutCell[] _gridLayoutCells;

		private List<GameObject> _reusablePrefabs;

		private int _pastFirstVisibleCell;

		private int _pastLastVisibleCell;

		private int _fixedNumberOfCellsDisplayed;

		public GridLayoutDataSource(GameObject cellPrefab, IGridCellData[] gridCellData, RectTransform cellAnchor, GridLayoutGroup cellGrid, RectTransform content, RectTransform viewPort)
		{
			_cellPrefab = cellPrefab;
			_gridCellData = gridCellData;
			_cellAnchor = cellAnchor;
			_cellGrid = cellGrid;
			_content = content;
			_viewPort = viewPort;
		}

		public void PopulateCellGrid()
		{
			_gridLayoutCells = CreateEmptyCells();
			FillGridWithEmptyRects();
			_reusablePrefabs = CreateReusableCellPrefabs();
			AddReusableCellsToView();
		}

		private GridLayoutCell[] CreateEmptyCells()
		{
			GridLayoutCell[] array = new GridLayoutCell[_gridCellData.Length];
			for (int i = 0; i < _gridCellData.Length; i++)
			{
				GameObject gameObject = new GameObject("Cell " + i.ToString());
				gameObject.AddComponent<RectTransform>();
				array[i] = new GridLayoutCell(gameObject);
			}
			return array;
		}

		private void FillGridWithEmptyRects()
		{
			for (int i = 0; i < _gridCellData.Length; i++)
			{
				_gridLayoutCells[i]._emptyParent.transform.SetParent(_cellAnchor);
				_gridLayoutCells[i]._emptyParent.transform.localPosition = Vector3.zero;
				_gridLayoutCells[i]._emptyParent.GetComponent<RectTransform>().localScale = new Vector3(1f, 1f, 1f);
			}
		}

		protected virtual List<GameObject> CreateReusableCellPrefabs()
		{
			int num = NeededNumberOfReusableCells();
			List<GameObject> list = new List<GameObject>();
			for (int i = 0; i < num; i++)
			{
				GameObject item = UnityEngine.Object.Instantiate(_cellPrefab);
				list.Add(item);
			}
			return list;
		}

		protected int NeededNumberOfReusableCells()
		{
			return CurrentVisibleCells().Count;
		}

		private List<int> CurrentVisibleCells()
		{
			List<int> list = new List<int>();
			if (_cellGrid.constraint == GridLayoutGroup.Constraint.FixedRowCount && _cellGrid.startAxis == GridLayoutGroup.Axis.Vertical)
			{
				int num = FirstVisibleCell();
				int num2 = LastVisibleCell();
				for (int i = num; i <= num2; i++)
				{
					list.Add(i);
				}
			}
			return list;
		}

		private int FirstVisibleCell()
		{
			if (_cellGrid.constraint == GridLayoutGroup.Constraint.FixedRowCount && _cellGrid.startAxis == GridLayoutGroup.Axis.Vertical)
			{
				Vector2 anchoredPosition = _content.anchoredPosition;
				float x = anchoredPosition.x;
				Vector2 anchorMin = _cellAnchor.anchorMin;
				float x2 = anchorMin.x;
				Vector2 sizeDelta = _content.sizeDelta;
				float num = x + x2 * sizeDelta.x;
				Vector2 cellSize = _cellGrid.cellSize;
				float x3 = cellSize.x;
				Vector2 spacing = _cellGrid.spacing;
				float num2 = x3 + spacing.x;
				int max = Mathf.Max((_gridCellData.Length - NumberOfCellsDisplayed()) / _cellGrid.constraintCount, 0);
				return Mathf.Clamp(Mathf.FloorToInt((0f - num) / num2), 0, max) * _cellGrid.constraintCount;
			}
			return 0;
		}

		private int NumberOfCellsDisplayed()
		{
			if (_fixedNumberOfCellsDisplayed <= 0)
			{
				Vector2 cellSize = _cellGrid.cellSize;
				float x = cellSize.x;
				Vector2 spacing = _cellGrid.spacing;
				float num = x + spacing.x;
				_fixedNumberOfCellsDisplayed = Mathf.CeilToInt(_viewPort.rect.width / num + 1f) * _cellGrid.constraintCount;
			}
			return Mathf.Min(_fixedNumberOfCellsDisplayed, _gridCellData.Length);
		}

		private int LastVisibleCell()
		{
			if (_cellGrid.constraint == GridLayoutGroup.Constraint.FixedRowCount && _cellGrid.startAxis == GridLayoutGroup.Axis.Vertical)
			{
				return FirstVisibleCell() + NumberOfCellsDisplayed() - 1;
			}
			return 0;
		}

		public void AddReusableCellsToView()
		{
			List<int> list = CurrentVisibleCells();
			for (int i = 0; i < _reusablePrefabs.Count; i++)
			{
				UpdateCell(i, _reusablePrefabs[i], _gridLayoutCells[list[i]]);
			}
		}

		private void UpdateCell(int index, GameObject reusablePrefab, GridLayoutCell gridLayoutCell)
		{
			IGridCell component = reusablePrefab.GetComponent<IGridCell>();
			component.UpdateCell(_gridCellData[index]);
			gridLayoutCell.cell = component;
			reusablePrefab.GetComponent<RectTransform>().offsetMax = Vector2.zero;
			reusablePrefab.GetComponent<RectTransform>().offsetMin = Vector2.zero;
		}

		public IEnumerator RecycleList()
		{
			int pastFirstVisibleCell = FirstVisibleCell();
			int pastLastVisibleCell = LastVisibleCell();
			Vector2 pastContentPosition = _content.anchoredPosition;
			while (true)
			{
				if (ContentIsMoving(pastContentPosition))
				{
					int num = FirstVisibleCell();
					int num2 = LastVisibleCell();
					if (LayoutIsHorizontal())
					{
						if (ContentMovingFromLeftToRight(pastFirstVisibleCell, num))
						{
							MoveCellIntervalToView(pastFirstVisibleCell, Mathf.Max(pastLastVisibleCell + 1, num), num2);
						}
						else if (ContentMovingFromRightToLeft(pastLastVisibleCell, num2))
						{
							MoveCellIntervalToView(Mathf.Max(num2 + 1, pastFirstVisibleCell), num, Mathf.Min(num2, pastFirstVisibleCell - 1));
						}
						pastFirstVisibleCell = num;
						pastLastVisibleCell = num2;
					}
					pastContentPosition = _content.anchoredPosition;
				}
				yield return new WaitForSeconds(Time.deltaTime);
			}
		}

		private bool ContentIsMoving(Vector2 pastContentPosition)
		{
			return !pastContentPosition.Equals(_content.anchoredPosition);
		}

		private bool LayoutIsHorizontal()
		{
			return _cellGrid.constraint == GridLayoutGroup.Constraint.FixedRowCount && _cellGrid.startAxis == GridLayoutGroup.Axis.Vertical;
		}

		private bool ContentMovingFromLeftToRight(int pastFirstVisibleCell, int firstVisibleCell)
		{
			return pastFirstVisibleCell < firstVisibleCell;
		}

		private bool ContentMovingFromRightToLeft(int pastLastVisibleCell, int lastVisibleCell)
		{
			return pastLastVisibleCell > lastVisibleCell;
		}

		private void MoveCellIntervalToView(int firstCellOutOfView, int firstCellOnView, int lastCellOnView)
		{
			for (int i = firstCellOnView; i <= lastCellOnView; i++)
			{
				int oldCell = i - firstCellOnView + firstCellOutOfView;
				RecycleCellIfPossible(oldCell, i);
			}
		}

		private void RecycleCellIfPossible(int oldCell, int newCell)
		{
			if (newCell >= 0 && newCell < _gridCellData.Length && oldCell >= 0 && oldCell < _gridCellData.Length && _gridLayoutCells[newCell].cell == null)
			{
				RecycleCell(oldCell, newCell);
			}
		}

		public void RecycleCell(int oldCell, int newCell)
		{
			_gridLayoutCells[newCell].cell = _gridLayoutCells[oldCell].cell;
			_gridLayoutCells[newCell].cell.UpdateCell(_gridCellData[newCell]);
			_gridLayoutCells[oldCell].cell = null;
		}

		public void CleanUp()
		{
			foreach (GameObject reusablePrefab in _reusablePrefabs)
			{
				UnityEngine.Object.Destroy(reusablePrefab);
			}
			GridLayoutCell[] gridLayoutCells = _gridLayoutCells;
			foreach (GridLayoutCell gridLayoutCell in gridLayoutCells)
			{
				UnityEngine.Object.Destroy(gridLayoutCell._emptyParent);
			}
			Array.Clear(_gridLayoutCells, 0, _gridLayoutCells.Length);
		}

		public void CenterListOnCell(int index)
		{
			float num = _viewPort.rect.width / 2f;
			Vector2 sizeDelta = _content.sizeDelta;
			float x = sizeDelta.x;
			Vector2 cellSize = _cellGrid.cellSize;
			float num2 = cellSize.x * (float)(_gridCellData.Length + 1);
			Vector2 spacing = _cellGrid.spacing;
			float num3 = x - (num2 + spacing.x * (float)_gridCellData.Length);
			Vector2 cellSize2 = _cellGrid.cellSize;
			float num4 = cellSize2.x * (float)index;
			Vector2 spacing2 = _cellGrid.spacing;
			float num5 = num4 + spacing2.x * (float)(index - 1) + num3 / 2f;
			RectTransform content = _content;
			float x2 = 0f - num5 + num;
			Vector3 localPosition = _content.localPosition;
			float y = localPosition.y;
			Vector3 localPosition2 = _content.localPosition;
			content.localPosition = new Vector3(x2, y, localPosition2.z);
		}

		public void CenterListOnCellIfOutside(int index)
		{
			CenterListOnCell(index + 1);
		}
	}
}
